﻿using HalconDotNet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using KstopaCommon;

namespace HVision.HControls
{
    public partial class HImageControl : UserControl
    {
        private HWindow hwindow;

        public HWindow Hwindow
        {
            get { return hwindow; }
        }

        private HImage himage;
        /// <summary>
        /// 显示图片
        /// </summary>
        public HImage Himage
        {
            get { return himage; }
            set
            {
                himage = value;
                FitImage();
            }
        }

        HTuple width, height;

        double mposition_row, mposition_col;

        double mposition_row1B, mposition_col1B;

        // 窗口和图像的宽高比
        double ratio_win, ratio_img;

        public List<HShape> HShapes = new List<HShape>();

        public List<HObject> HObjects = new List<HObject>();

        public List<HXLD> HXLDs = new List<HXLD>();

        public HImageControl()
        {
            InitializeComponent();
            hwindow = hWindowControl1.HalconWindow;
            if (GetIsDesignMode() == false)
            {
                //HOperatorSet.SetWindowAttr("background_color", new HTuple("#0A0A64"));
                //hWindowControl1.HalconWindow.OpenWindow(0, 0, hWindowControl1.Width, hWindowControl1.Height, hWindowControl1.Handle, "visible", "");
            }
        }

        public void RefreshControl()
        {
            FitImage();
        }

        /// <summary>
        ///  适应图片
        /// </summary>
        private void FitImage()
        {
            try
            {
                if (himage != null)
                {
                    HOperatorSet.GetImageSize(himage, out width, out height);
                    ratio_win = (double)hWindowControl1.WindowSize.Width / (double)hWindowControl1.WindowSize.Height;
                    ratio_img = (double)width / (double)height;
                    int _beginRow, _begin_Col, _endRow, _endCol;
                    if (ratio_win >= ratio_img)
                    {
                        _beginRow = 0;
                        _endRow = (int)height.D - 1;
                        _begin_Col = (int)(-width.D * (ratio_win / ratio_img - 1d) / 2d);
                        _endCol = (int)(width.D + width.D * (ratio_win / ratio_img - 1d) / 2d);
                    }
                    else
                    {
                        _begin_Col = 0;
                        _endCol = (int)width.D - 1;
                        _beginRow = (int)(-height.D * (ratio_img / ratio_win - 1d) / 2d);
                        _endRow = (int)(height.D + height.D * (ratio_img / ratio_win - 1d) / 2d);
                    }
                    hwindow.SetPart(_beginRow, _begin_Col, _endRow, _endCol);
                    //hwindow.ClearWindow();
                    //HSystem.SetSystem("flush_graphic", "true");
                    //hwindow.DispObj(himage);
                    //HSystem.SetSystem("flush_graphic", "false");
                    Draw();
                }
            }
            catch (HalconException exc)
            {
                MessageBox.Show(exc.Message);
            }
        }

        int Wt, Ht;
        int button_state, button_stateB;
        int current_beginRow1, current_beginCol1, current_endRow1, current_endCol1;
        private void hWindowControl1_Resize(object sender, EventArgs e)
        {
            FitImage();
        }

        int zoom_beginRow1, zoom_beginCol1, zoom_endRow1, zoom_endCol1;
        private void hWindowControl1_HMouseWheel(object sender, HalconDotNet.HMouseEventArgs e)
        {
            if (himage != null)
            {
                try
                {
                    hwindow.GetMpositionSubPix(out mposition_row, out mposition_col, out button_state);
                    hwindow.GetPart(out current_beginRow1, out current_beginCol1, out current_endRow1, out current_endCol1);
                    Ht = current_endRow1 - current_beginRow1;
                    Wt = current_endCol1 - current_beginCol1;
                }
                catch (HalconException)
                {
                }
                if (e.Delta > 0) // 放大图像
                {
                    if (Ht > 4)
                    {
                        zoom_beginRow1 = (int)(current_beginRow1 + (mposition_row - current_beginRow1) * 0.300d);
                        zoom_beginCol1 = (int)(current_beginCol1 + (mposition_col - current_beginCol1) * 0.300d);
                        zoom_endRow1 = (int)(current_endRow1 - (current_endRow1 - mposition_row) * 0.300d);
                        zoom_endCol1 = (int)(current_endCol1 - (current_endCol1 - mposition_col) * 0.300d);
                        hwindow.SetPart(zoom_beginRow1, zoom_beginCol1, zoom_endRow1, zoom_endCol1);
                        try
                        {
                            Draw();
                        }
                        catch (HalconException)
                        {
                        }
                    }
                }

                else // 缩小图像
                {

                    if (Ht < 8000)
                    {
                        zoom_beginRow1 = (int)(mposition_row - (mposition_row - current_beginRow1) / 0.700d);
                        zoom_beginCol1 = (int)(mposition_col - (mposition_col - current_beginCol1) / 0.700d);
                        zoom_endRow1 = (int)(mposition_row + (current_endRow1 - mposition_row) / 0.700d);
                        zoom_endCol1 = (int)(mposition_col + (current_endCol1 - mposition_col) / 0.700d);
                        hwindow.SetPart(zoom_beginRow1, zoom_beginCol1, zoom_endRow1, zoom_endCol1);
                        try
                        {
                            Draw();
                        }
                        catch (HalconException)
                        {
                        }
                    }

                }

            }
        }

        HTuple channel_count;
        HTuple hv_mposition_row1, hv_mposition_col1, hv_button_state1, hv_Grayval1;

        private void 保存窗口ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WriteDumpWindow();
        }

        bool winCrossDraw = false;
        private void 中心十字ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            winCrossDraw = !winCrossDraw;
            Draw();
        }

        private void 保存图片ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WriteImage();
        }

        private void 适应图片ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FitImage();
        }

        private void hWindowControl1_HMouseMove(object sender, HalconDotNet.HMouseEventArgs e)
        {
            try
            {
                if (himage != null)
                {
                    HOperatorSet.CountChannels(himage, out channel_count);
                    hwindow.GetMpositionSubPix(out mposition_row, out mposition_col, out button_state);
                    string str_size = "size:" + width + "*" + height + "    ";
                    string str_position = String.Format("x:{0:0.00},y:{1:0.00}", mposition_col, mposition_row);
                    try
                    {
                        if (width > mposition_col & height > mposition_row & mposition_col > 1 & mposition_row > 1)
                        {
                            HOperatorSet.GetMposition(hwindow, out hv_mposition_row1, out hv_mposition_col1, out hv_button_state1);
                            HOperatorSet.GetGrayval(himage, hv_mposition_row1, hv_mposition_col1, out hv_Grayval1);//中读取灰度值
                            if (channel_count > 1)
                                toolLabel1.Text = string.Format(str_size + str_position + " " + "value=" + "R:{0},G:{1},B:{2}", +hv_Grayval1.TupleSelect(0), hv_Grayval1.TupleSelect(1), hv_Grayval1.TupleSelect(2));
                            else
                                toolLabel1.Text = str_size + str_position + "   " + "value=" + hv_Grayval1.ToString();
                        }
                        else
                            toolLabel1.Text = str_size + str_position + "   " + "value=" + 0;
                    }
                    catch (HalconException)
                    {
                    }

                    if (button_state == 1)//left
                    {
                        if (mousedown == false)
                        {
                            return;
                        }
                        if (shapeSelect != null)
                        {
                            shapeSelect.MoveByHandle(e.X, e.Y);
                            if (shapeSelect is HLineGuage)
                            {
                                ((HLineGuage)shapeSelect).Measure(Himage);
                            }
                            Draw();
                        }
                    }
                    else if (button_state == 2)//middle
                    {
                        Cursor.Current = Cursors.SizeAll;//("SizeAll");
                        int current_beginRow2, current_beginCol2, current_endRow2, current_endCol2;
                        int dbRowMove1, dbColMove1;
                        dbRowMove1 = (int)(mposition_row1B - mposition_row);
                        dbColMove1 = (int)(mposition_col1B - mposition_col);
                        hwindow.GetPart(out current_beginRow2, out current_beginCol2, out current_endRow2, out current_endCol2);
                        hwindow.SetPart(current_beginRow2 + dbRowMove1, current_beginCol2 + dbColMove1, current_endRow2 + dbRowMove1, current_endCol2 + dbColMove1);
                        try
                        {
                            Draw();
                        }
                        catch (HalconException)
                        {
                        }
                    }
                    //else if (button_state == 2)
                    //{
                    //    FitImage();
                    //}
                    else
                    {
                        hwindow.GetMpositionSubPix(out mposition_row1B, out mposition_col1B, out button_stateB);
                    }

                }
            }
            catch (HalconException exc)
            {
                Console.WriteLine(exc.Message);
                LogHelper.ErrorLog(exc.Message, null);
            }
        }

        bool mousedown = false;
        int epsilon = 30;
        HShape shapeSelect = null;
        private void hWindowControl1_HMouseDown(object sender, HalconDotNet.HMouseEventArgs e)
        {
            mousedown = true;
            double dist = 100000;
            HShape shape = null;
            foreach (var item in HShapes)
            {
                double dist1 = item.DistToClosestHandle(e.X, e.Y);
                if (dist1 < dist)
                {
                    dist = dist1;
                    shape = item;
                }
            }
            if (dist < epsilon)
            {
                shapeSelect = shape;
            }
        }

        private void hWindowControl1_HMouseUp(object sender, HalconDotNet.HMouseEventArgs e)
        {
            mousedown = false;
            shapeSelect = null;
        }

        private void Draw()
        {
            hwindow.ClearWindow();
            HSystem.SetSystem("flush_graphic", "true");
            hwindow.DispObj(himage);
            foreach (var item in HShapes)
            {
                item.Draw(hwindow);
            }
            foreach (var item in HObjects)
            {
                hwindow.DispObj(item);
            }
            if (winCrossDraw)
            {
                DispWindowCross(himage);
            }
            HSystem.SetSystem("flush_graphic", "false");
        }

        private void disp_message(HTuple hv_String, HTuple hv_CoordSystem, HTuple hv_Row, HTuple hv_Column, HTuple hv_Color, HTuple hv_Box, HTuple hv_BoxColor)
        {
            disp_message(hwindow, hv_String, hv_CoordSystem, hv_Row, hv_Column, hv_Color, hv_Box, hv_BoxColor);
        }

        private void disp_message(HTuple hv_WindowHandle, HTuple hv_String, HTuple hv_CoordSystem, HTuple hv_Row, HTuple hv_Column, HTuple hv_Color, HTuple hv_Box, HTuple hv_BoxColor)
        {
            // Local iconic variables 
            // Local control variables
            HTuple hv_Red = null, hv_Green = null, hv_Blue = null;
            HTuple hv_Row1Part = null, hv_Column1Part = null, hv_Row2Part = null;
            HTuple hv_Column2Part = null, hv_RowWin = null, hv_ColumnWin = null;
            HTuple hv_WidthWin = new HTuple(), hv_HeightWin = null;
            HTuple hv_MaxAscent = null, hv_MaxDescent = null, hv_MaxWidth = null;
            HTuple hv_MaxHeight = null, hv_R1 = new HTuple(), hv_C1 = new HTuple();
            HTuple hv_FactorRow = new HTuple(), hv_FactorColumn = new HTuple();
            HTuple hv_UseShadow = null, hv_ShadowColor = null, hv_Exception = new HTuple();
            HTuple hv_Width = new HTuple(), hv_Index = new HTuple();
            HTuple hv_Ascent = new HTuple(), hv_Descent = new HTuple();
            HTuple hv_W = new HTuple(), hv_H = new HTuple(), hv_FrameHeight = new HTuple();
            HTuple hv_FrameWidth = new HTuple(), hv_R2 = new HTuple();
            HTuple hv_C2 = new HTuple(), hv_DrawMode = new HTuple();
            HTuple hv_CurrentColor = new HTuple();
            HTuple hv_Box_COPY_INP_TMP = hv_Box.Clone();
            HTuple hv_Color_COPY_INP_TMP = hv_Color.Clone();
            HTuple hv_Column_COPY_INP_TMP = hv_Column.Clone();
            HTuple hv_Row_COPY_INP_TMP = hv_Row.Clone();
            HTuple hv_String_COPY_INP_TMP = hv_String.Clone();

            // Initialize local and output iconic variables
            HOperatorSet.GetRgb(hv_WindowHandle, out hv_Red, out hv_Green, out hv_Blue);
            HOperatorSet.GetPart(hv_WindowHandle, out hv_Row1Part, out hv_Column1Part,
                out hv_Row2Part, out hv_Column2Part);
            HOperatorSet.GetWindowExtents(hv_WindowHandle, out hv_RowWin, out hv_ColumnWin,
                out hv_WidthWin, out hv_HeightWin);
            HOperatorSet.SetPart(hv_WindowHandle, 0, 0, hv_HeightWin - 1, hv_WidthWin - 1);
            //default settings
            if ((int)(new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(-1))) != 0)
            {
                hv_Row_COPY_INP_TMP = 12;
            }
            if ((int)(new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(-1))) != 0)
            {
                hv_Column_COPY_INP_TMP = 12;
            }
            if ((int)(new HTuple(hv_Color_COPY_INP_TMP.TupleEqual(new HTuple()))) != 0)
            {
                hv_Color_COPY_INP_TMP = "";
            }
            //
            hv_String_COPY_INP_TMP = ((("" + hv_String_COPY_INP_TMP) + "")).TupleSplit("\n");
            //
            //Estimate extentions of text depending on font size.
            HOperatorSet.GetFontExtents(hv_WindowHandle, out hv_MaxAscent, out hv_MaxDescent,
                out hv_MaxWidth, out hv_MaxHeight);
            if ((int)(new HTuple(hv_CoordSystem.TupleEqual("window"))) != 0)
            {
                hv_R1 = hv_Row_COPY_INP_TMP.Clone();
                hv_C1 = hv_Column_COPY_INP_TMP.Clone();
            }
            else
            {
                //Transform image to window coordinates
                hv_FactorRow = (1.0 * hv_HeightWin) / ((hv_Row2Part - hv_Row1Part) + 1);
                hv_FactorColumn = (1.0 * hv_WidthWin) / ((hv_Column2Part - hv_Column1Part) + 1);
                hv_R1 = ((hv_Row_COPY_INP_TMP - hv_Row1Part) + 0.5) * hv_FactorRow;
                hv_C1 = ((hv_Column_COPY_INP_TMP - hv_Column1Part) + 0.5) * hv_FactorColumn;
            }
            //
            //Display text box depending on text size
            hv_UseShadow = 0;
            hv_ShadowColor = "gray";
            if ((int)(new HTuple(((hv_Box_COPY_INP_TMP.TupleSelect(0))).TupleEqual("true"))) != 0)
            {
                if (hv_Box_COPY_INP_TMP == null)
                    hv_Box_COPY_INP_TMP = new HTuple();
                hv_Box_COPY_INP_TMP[0] = hv_BoxColor;
                hv_ShadowColor = "#f28d26";
                if (hv_Box_COPY_INP_TMP == null)
                    hv_Box_COPY_INP_TMP = new HTuple();
                hv_Box_COPY_INP_TMP[0] = "#33ff66";
                hv_ShadowColor = "#f2ffff";

            }
            if ((int)(new HTuple((new HTuple(hv_Box_COPY_INP_TMP.TupleLength())).TupleGreater(
                1))) != 0)
            {
                if ((int)(new HTuple(((hv_Box_COPY_INP_TMP.TupleSelect(1))).TupleEqual("true"))) != 0)
                {
                    //Use default ShadowColor set above
                }
                else if ((int)(new HTuple(((hv_Box_COPY_INP_TMP.TupleSelect(1))).TupleEqual(
                    "false"))) != 0)
                {
                    hv_UseShadow = 0;
                }
                else
                {
                    hv_ShadowColor = hv_Box_COPY_INP_TMP[1];
                    //Valid color?
                    try
                    {
                        HOperatorSet.SetColor(hv_WindowHandle, hv_Box_COPY_INP_TMP.TupleSelect(
                            1));
                    }
                    // catch (Exception) 
                    catch (HalconException HDevExpDefaultException1)
                    {
                        HDevExpDefaultException1.ToHTuple(out hv_Exception);
                        hv_Exception = "Wrong value of control parameter Box[1] (must be a 'true', 'false', or a valid color string)";
                        throw new HalconException(hv_Exception);
                    }
                }
            }
            if ((int)(new HTuple(((hv_Box_COPY_INP_TMP.TupleSelect(0))).TupleNotEqual("false"))) != 0)
            {
                //Valid color?
                try
                {
                    HOperatorSet.SetColor(hv_WindowHandle, hv_Box_COPY_INP_TMP.TupleSelect(
                        0));
                }
                // catch (Exception) 
                catch (HalconException HDevExpDefaultException1)
                {
                    HDevExpDefaultException1.ToHTuple(out hv_Exception);
                    hv_Exception = "Wrong value of control parameter Box[0] (must be a 'true', 'false', or a valid color string)";
                    throw new HalconException(hv_Exception);
                }
                //Calculate box extents
                hv_String_COPY_INP_TMP = (" " + hv_String_COPY_INP_TMP) + " ";
                hv_Width = new HTuple();
                for (hv_Index = 0; (int)hv_Index <= (int)((new HTuple(hv_String_COPY_INP_TMP.TupleLength()
                    )) - 1); hv_Index = (int)hv_Index + 1)
                {
                    HOperatorSet.GetStringExtents(hv_WindowHandle, hv_String_COPY_INP_TMP.TupleSelect(
                        hv_Index), out hv_Ascent, out hv_Descent, out hv_W, out hv_H);
                    hv_Width = hv_Width.TupleConcat(hv_W);
                }
                hv_FrameHeight = hv_MaxHeight * (new HTuple(hv_String_COPY_INP_TMP.TupleLength()
                    ));
                hv_FrameWidth = (((new HTuple(0)).TupleConcat(hv_Width))).TupleMax();
                hv_R2 = hv_R1 + hv_FrameHeight;
                hv_C2 = hv_C1 + hv_FrameWidth;
                //Display rectangles
                HOperatorSet.GetDraw(hv_WindowHandle, out hv_DrawMode);
                HOperatorSet.SetDraw(hv_WindowHandle, "fill");
                //Set shadow color
                HOperatorSet.SetColor(hv_WindowHandle, hv_ShadowColor);
                if ((int)(hv_UseShadow) != 0)
                {
                    HOperatorSet.DispRectangle1(hv_WindowHandle, hv_R1 + 1, hv_C1 + 1, hv_R2 + 1,
                        hv_C2 + 1);
                }
                //Set box color
                HOperatorSet.SetColor(hv_WindowHandle, hv_Box_COPY_INP_TMP.TupleSelect(
                    0));
                HOperatorSet.DispRectangle1(hv_WindowHandle, hv_R1, hv_C1, hv_R2, hv_C2);
                HOperatorSet.SetDraw(hv_WindowHandle, hv_DrawMode);
            }
            //Write text.
            for (hv_Index = 0; (int)hv_Index <= (int)((new HTuple(hv_String_COPY_INP_TMP.TupleLength()
                )) - 1); hv_Index = (int)hv_Index + 1)
            {
                hv_CurrentColor = hv_Color_COPY_INP_TMP.TupleSelect(hv_Index % (new HTuple(hv_Color_COPY_INP_TMP.TupleLength()
                    )));
                if ((int)((new HTuple(hv_CurrentColor.TupleNotEqual(""))).TupleAnd(new HTuple(hv_CurrentColor.TupleNotEqual(
                    "auto")))) != 0)
                {
                    HOperatorSet.SetColor(hv_WindowHandle, hv_CurrentColor);
                }
                else
                {
                    HOperatorSet.SetRgb(hv_WindowHandle, hv_Red, hv_Green, hv_Blue);
                }
                hv_Row_COPY_INP_TMP = hv_R1 + (hv_MaxHeight * hv_Index);
                HOperatorSet.SetTposition(hv_WindowHandle, hv_Row_COPY_INP_TMP, hv_C1);
                HOperatorSet.WriteString(hv_WindowHandle, hv_String_COPY_INP_TMP.TupleSelect(
                    hv_Index));
            }
            //Reset changed window settings
            HOperatorSet.SetRgb(hv_WindowHandle, hv_Red, hv_Green, hv_Blue);
            HOperatorSet.SetPart(hv_WindowHandle, hv_Row1Part, hv_Column1Part, hv_Row2Part,
                hv_Column2Part);

            return;
        }

        /// <summary>
        /// 获取当前是否处于设计器模式
        /// </summary>
        /// <remarks>
        /// 在程序初始化时获取一次比较准确，若需要时获取可能由于布局嵌套导致获取不正确，如GridControl-GridView组合。
        /// </remarks>
        /// <returns>是否为设计器模式</returns>
        private bool GetIsDesignMode()
        {
            return (this.GetService(typeof(System.ComponentModel.Design.IDesignerHost)) != null
                || LicenseManager.UsageMode == LicenseUsageMode.Designtime);
        }

        private void DispWindowCross(HObject ho_Image)
        {
            try
            {
                HObject ho_Contour1, ho_Contour2;
                HTuple hv_Width = null, hv_Height = null;
                HOperatorSet.GenEmptyObj(out ho_Contour1);
                HOperatorSet.GenEmptyObj(out ho_Contour2);
                HOperatorSet.SetColor(hwindow, "red");
                HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
                HOperatorSet.GenContourPolygonXld(out ho_Contour1, (new HTuple(0)).TupleConcat(hv_Height), ((hv_Width / 2)).TupleConcat(hv_Width / 2));
                HOperatorSet.GenContourPolygonXld(out ho_Contour2, ((hv_Height / 2)).TupleConcat(hv_Height / 2), (new HTuple(0)).TupleConcat(hv_Width));
                HOperatorSet.DispObj(ho_Contour1, hwindow);
                HOperatorSet.DispObj(ho_Contour2, hwindow);
            }
            catch { }
        }

        private void WriteImage()
        {
            if (himage != null)
            {
                string imageFileName, imagefomrat = "bmp";
                saveFileDialog1.Filter = "BMP图像|*.bmp|JPEG图像|*.jpg|PNG图像|*.png";// "JPEG文件|*.jpg*|BMP文件|*.bmp*|PNG文件|*.png*";
                if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    switch (saveFileDialog1.FilterIndex)
                    {
                        case 1:
                            imagefomrat = "bmp";
                            break;
                        case 2:
                            imagefomrat = "jpg";
                            break;
                        case 3:
                            imagefomrat = "png";
                            break;
                    }
                    imageFileName = saveFileDialog1.FileName;
                    HOperatorSet.WriteImage(himage, imagefomrat, 0, imageFileName);
                }
            }
        }

        private void WriteDumpWindow()
        {
            if (himage != null)
            {
                string imageFileName, imagefomrat = "bmp";
                saveFileDialog1.Filter = "BMP图像|*.bmp|JPEG图像|*.jpg|PNG图像|*.png";// "JPEG文件|*.jpg*|BMP文件|*.bmp*|PNG文件|*.jpg*|BMP文件|*.bmp*|PNG文件|*.png*";
                if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    switch (saveFileDialog1.FilterIndex)
                    {
                        case 1:
                            imagefomrat = "bmp";
                            break;
                        case 2:
                            imagefomrat = "jpg";
                            break;
                        case 3:
                            imagefomrat = "png";
                            break;
                    }
                    imageFileName = saveFileDialog1.FileName;
                    HOperatorSet.DumpWindow(hwindow, imagefomrat, imageFileName);
                }
            }
        }

    }
}
